using System;
using OhioState.AssetManaged;
using OhioState.Math;
using OhioState.Graphics;

namespace OhioState.Physics
{
    /// <summary>
    /// RigidBody class 
    /// </summary>
    public class RigidBody : SharedAsset, IDrawable, 
        IDynamicModel
    {
        IDrawable _realDrawable;

        /// <summary>
        /// Get Accessor for Drawable
        /// </summary>
        public IAssetManaged Drawable
        {
            get { return _realDrawable as IAssetManaged; }
        }
        /// <summary>
        /// Constructor for RigidBody
        /// </summary>
        /// <param name="name">Name of the object</param>
        /// <param name="drawable">Drawable object</param>
        public RigidBody(String name, IDrawable drawable)
            : base(name)
        {
            _realDrawable = drawable;
            _updateCommand = new RigidBodyUpdateCommand(this);
        }

        #region IDrawable Members
        /// <summary>
        /// Implementation of IDrawable BoundingVolume 
        /// </summary>
        public OhioState.Graphics.IBoundingVolume BoundingVolume
        {
            get
            {
                IBoundingVolume bBox = _realDrawable.BoundingVolume;
                //
                // Transform the bounding volume
                //
                // TODO:
                return bBox;
            }
        }
        /// <summary>
        /// Get Set Accessor for Material
        /// </summary>
        public OhioState.Graphics.IMaterial Material
        {
            get
            {
                return _realDrawable.Material;
            }
            set
            {
                _realDrawable.Material = value;
            }
        }

        /// <summary>
        /// IDrawable implementation of Render Method
        /// </summary>
        /// <param name="panel"></param>
        public void Render(IRenderPanel panel)
        {
            // Proxy object, so the render should not do anything anyhow.
        }
        
        #endregion

        #region IDynamicModel Members
        private Vector3 _position = new Vector3();
        /// <summary>
        /// Implementation of IDynamicModel Get Position
        /// </summary>
        public Vector3 Position
        {
            get
            {
                lock (this)
                {
                    return _position;
                }
            }
        }
        private Vector3 _velocity = new Vector3();
        /// <summary>
        /// Implementation of IDynamicModel Get Velocity
        /// </summary>
        
        public Vector3 Velocity
        {
            get
            {
                lock (this)
                {
                    return _velocity;
                }
            }
        }

        private float _maximumVelocity = 30.7f;
        /// <summary>
        /// Implementation of IDynamicModel Get Set Maximum Velocity
        /// </summary>
      
        public float MaximumVelocity
        {
            get { return _maximumVelocity; }
            set 
            {
                if (value >= 0.0f)
                {
                    _maximumVelocity = value;
                }
            }
        }
        private DynamicModelUpdateCommand _updateCommand;
        /// <summary>
        /// Implementation of IDynamicModel Get Set UpdateCommand
        /// </summary>
        public DynamicModelUpdateCommand Updater
        {
            get { return _updateCommand; }
            set { _updateCommand = value; }
        }
        /// <summary>
        /// IDynamicModel implementation of Update method
        /// </summary>
        /// <param name="time">time</param>
        /// <param name="elapsedSeconds">elapsed time in seconds</param>
        public void Update(double time, double elapsedSeconds)
        {
            DynamicModelUpdateCommand command = _updateCommand;
            command.Execute(time, elapsedSeconds);
            //_position = _position + (float)elapsedSeconds * _velocity;
        }
        /// <summary>
        /// Implementation of IDynamicModel SetPosition method
        /// </summary>
        /// <param name="position">position</param>
        public void SetPosition(Vector3 position)
        {
            lock (this)
            {
                _position = position;
            }
            FireUpdateChangedEvent(this);
        }
        /// <summary>
        /// Implementation of IDynamicModel SetVelocity method
        /// </summary>
        /// <param name="velocity"></param>
        public void SetVelocity(Vector3 velocity)
        {
            lock (this)
            {
                _velocity = velocity;
            }
            FireUpdateChangedEvent(this);
        }
        #endregion
    }
}
